package AEF::ModuleGrabber;

use Modern::Perl;
use Moose;
use Log::Log4perl qw( :easy );

require AEF::AEFProcessor;
require AEF::Module;

extends 'AEF::AEFProcessor';

has 'modules' => (
	is => 'rw', 
	isa => 'ArrayRef[AEF::Module]', 
	default => sub { [] }
);

has 'only_exes_and_dlls' => (
	is => 'rw',
	isa => 'Bool',
);

has 'dll' => (
	is => 'rw',
	isa => 'Int',
);

has 'lib' => (
	is => 'rw',
	isa => 'Int',
);

has 'flags_read' => (
	is => 'rw',
	isa => 'Int',
	default => 0,
);

has '+typeFormats' => (
	default => sub { 
		{
			0x0a => 'C',
			0x0b => 'C',
			0x10f => 'CCCCCCCCC',
			0x20 => 'Z*', 
		};
	}
);

around 'RequireDataForType' => sub
{
	my $orig = shift;
	my $self = shift;
	my $type = shift;

	my $logger = get_logger();
	my $require = $self->$orig($type);
	if($require)
	{
		if($self->only_exes_and_dlls && $self->flags_read == 2)
		{
			if($self->dll != $self->lib)
			{
				# not an exe or dll so don't bother processing any more.
				$logger->debug("Not processing any more because not a dll or exe");
				$self->doneProcessing(1);
			}
		}
		if(!($type == 0x20 || $type == 0x0a || $type == 0xb || $type == 0x10f))
		{
			$require = 0;
		}
	}
	return $require;
};

override 'ProcessBlock' => sub 
{
	my $self = shift;
	my ($type, $data_chunk, $ptr) = @_;
	my $logger = get_logger();
	given($type)
	{
		when(0x0a)
		{
			$logger->debug("Read lib flag");
			$self->lib($data_chunk);
			$self->flags_read($self->flags_read+1);
		}
		when(0x0b)
		{
			$logger->debug("Read dll flag");
			$self->dll($data_chunk);
			$self->flags_read($self->flags_read+1);
		}
		when (0x10f)
		{
			$self->lib($data_chunk->[4]);
			$self->dll($data_chunk->[8]);
			$self->flags_read(2);
		}
		when(0x20)
		{
			my ($module_name) = $data_chunk;
			$logger->debug("Encountered module $module_name");
			my $module = AEF::Module->new(
				name => $module_name,
				ptr => $ptr,
			);
			push @{$self->modules}, $module;
		}
	}
};


1;

no Moose;
